package org.ucas.faker.web.service.fishbone;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.ucas.faker.web.service.graph.AdvancedStatService;
import org.ucas.faker.web.service.graph.TreeTermService;
import org.ucas.faker.web.utils.fishbone.Circle;
import org.ucas.faker.web.utils.fishbone.FishboneNode;
import org.ucas.faker.web.utils.fishbone.FishboneResult;
import org.ucas.faker.web.utils.fishbone.Line;
import org.ucas.faker.web.utils.fishbone.Tag;
import org.ucas.faker.web.utils.model.TreeTerm;


@Service
@Transactional
public class FishboneService extends AdvancedStatService {

    @Autowired
    private TreeTermService treeTermService;

    public FishboneResult test(long depotId){
        FishboneNode root = constructFishboneList(depotId);
        FishboneResult result = drawFishboneMap(root);
        return result;
    }

    public FishboneNode constructFishboneList(long treeId){
        TreeTerm treeRoot = treeTermService.getTreeTerm(treeId);

        FishboneNode root = new FishboneNode(treeRoot.getWord_CN());
        root.setLevel(0);
        for (TreeTerm subTerm : treeRoot.getChildTermList()){
            FishboneNode subNode = new FishboneNode(subTerm.getWord_CN());
            subNode.setLevel(1);
            subNode.setParent(root);
            root.addChild(subNode);

            for (TreeTerm leafTerm : subTerm.getChildTermList()){
                FishboneNode tmpNode = new FishboneNode(leafTerm.getWord_CN());
                tmpNode.setLevel(2);
                tmpNode.setParent(subNode);
                subNode.addChild(tmpNode);
            }
        }
        root.printTree();
        return root;
    }

    private FishboneNode testGenerateFishbone(){
        FishboneNode root = new FishboneNode("存储器");
        root.setLevel(0);
        for (int i=0;i<8;i++){
            FishboneNode subNode = new FishboneNode("二级节点"+(i+1));
            subNode.setLevel(1);
            subNode.setParent(root);
            root.addChild(subNode);

            for (int j=0; j<6; j++){
                FishboneNode tmpNode = new FishboneNode("三级节点"+(i+1)+"#"+(j+1));
                tmpNode.setLevel(2);
                tmpNode.setParent(subNode);
                subNode.addChild(tmpNode);

                /*for (int k=0; k<5; k++){
                    FishboneNode lNode = new FishboneNode("四级节点"+(j+1)+"#"+(k+1));
                    lNode.setLevel(3);
                    lNode.setParent(tmpNode);
                    tmpNode.addChild(lNode);
                }*/
            }
        }
        root.printTree();
        return root;
    }

    public FishboneResult drawFishboneMap(FishboneNode root){
        FishboneResult result = new FishboneResult();

        double levelOneStep = 10.0;
        double levelOneRadius = 3.0;
        double levelOneTextSize = 14.0;

        Tag rootTag = new Tag().setX(0).setY(0).setSize(levelOneTextSize).setText(root.getTag());
        result.addTag(rootTag);

        double levelOneX = 8.0;
        Line rootLine = new Line().setStartPoint(new double[]{0,0}).setEndPoint(new double[]{levelOneX, 0});
        result.addLine(rootLine);

        //二级节点
        for (int i=0;i<root.getChildrenList().size();i++){
            double coverLength = levelOneStep*0.9;
            FishboneNode node = root.getChildrenList().get(i);
            double[] startLinePoint = {levelOneX + (i/2)*levelOneStep, 0};
            double[] endLinePoint = {startLinePoint[0]+coverLength, 0+Math.pow(-1, i)*coverLength*1.5};

            /*System.out.println("tag="+node.getTag());
            System.out.println("start: x="+startLinePoint[0]+" y="+startLinePoint[1]);
            System.out.println("end: x="+endLinePoint[0]+" y="+endLinePoint[1]);*/

            Tag nodeTag = new Tag().setCoordinate(endLinePoint).setSize(levelOneTextSize).setText(node.getTag());
            result.addTag(nodeTag);
            nodeTag.print();

            Line line = new Line().setStartPoint(startLinePoint).setEndPoint(endLinePoint);
            result.addLine(line);
            line.print();

            Circle circle = new Circle().setCenter(endLinePoint).setRadius(10);
            result.addCircle(circle);

            //三级节点
            int subNodeNum = node.getChildrenList().size();
            for (int j=0;j<subNodeNum;j++){
                FishboneNode subNode = node.getChildrenList().get(j);
                double lambda = 1.0/(subNodeNum+1.0)*(j+1.0);


                double[] subStartLinePoint = {startLinePoint[0]*lambda+endLinePoint[0]*(1-lambda),
                                              startLinePoint[1]*lambda+endLinePoint[1]*(1-lambda)};

                double[] subEndLinePoint = {subStartLinePoint[0]+levelOneStep*0.8, subStartLinePoint[1]};

                /*System.out.println("subNode tag="+subNode.getTag());
                System.out.println("start: x="+subStartLinePoint[0]+" y="+subStartLinePoint[1]);
                System.out.println("end: x="+subEndLinePoint[0]+" y="+subEndLinePoint[1]);*/

                Tag subTag = new Tag().setCoordinate(subEndLinePoint).setSize(levelOneTextSize).setText(subNode.getTag());
                result.addTag(subTag);
                subTag.print();

                Line subLine = new Line().setStartPoint(subStartLinePoint).setEndPoint(subEndLinePoint);
                result.addLine(subLine);
                subLine.print();

                Circle subCircle = new Circle().setCenter(subEndLinePoint).setRadius(7);
                result.addCircle(subCircle);

                //四级节点
                int lastNodeNum = subNode.getChildrenList().size();
                double levelThreeStep = Math.abs(subStartLinePoint[0]-subEndLinePoint[0])/(Math.ceil(lastNodeNum/2.0) + 1.0);
                double lastCoverLength = levelThreeStep*0.4;
                for (int k=0;k<lastNodeNum;k++){
                    FishboneNode lastNode = subNode.getChildrenList().get(k);

                    double[] lastStartLinePoint = {subStartLinePoint[0]+(k/2+1)*levelThreeStep, subStartLinePoint[1]};
                    double[] lastEndLinePoint = {lastStartLinePoint[0]+lastCoverLength,
                                                 lastStartLinePoint[1]+Math.pow(-1,k)*lastCoverLength*1.5};

                    /*System.out.println("lastNode tag="+subNode.getTag());
                    System.out.println("start: x="+lastStartLinePoint[0]+" y="+lastStartLinePoint[1]);
                    System.out.println("end: x="+lastEndLinePoint[0]+" y="+lastEndLinePoint[1]);*/

                    Tag lastTag = new Tag().setCoordinate(lastEndLinePoint).setSize(levelOneTextSize).setText(lastNode.getTag());
                    result.addTag(lastTag);
                    lastTag.print();

                    Line lastLine = new Line().setStartPoint(lastStartLinePoint).setEndPoint(lastEndLinePoint);
                    result.addLine(lastLine);
                    lastLine.print();

                    Circle lastCircle = new Circle().setCenter(lastEndLinePoint).setRadius(4);
                    result.addCircle(lastCircle);
                }
            }
        }
        return result;
    }

}
